package com.jjb.common.view;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

/**
 * 精准计算
 *     RoundingMode:
 *                  ROUND_UP 若舍入位为非零，则对舍入部分的前一位数字加1；若舍入位为零，则直接舍弃。即为向外取整模式。
 *                  ROUND_DOWN：不论舍入位是否为零，都直接舍弃。即为向内取整模式。
 *                  ROUND_CEILING：若 BigDecimal 为正，则舍入行为与 ROUND_UP 相同；若为负，则舍入行为与 ROUND_DOWN 相同。即为向上取整模式。
 *                  ROUND_FLOOR：若 BigDecimal 为正，则舍入行为与 ROUND_DOWN 相同；若为负，则舍入行为与 ROUND_UP 相同。即为向下取整模式。
 *                  HALF_UP 若舍入位大于等于5，则对舍入部分的前一位数字加1；若舍入位小于5，则直接舍弃。即为四舍五入模式。
 *                  HALF_DOWN 若舍入位大于5，则对舍入部分的前一位数字加1；若舍入位小于等于5，则直接舍弃。即为五舍六入模式。
 *                  HALF_EVEN  若（舍入位大于5）或者（舍入位等于5且前一位为奇数），则对舍入部分的前一位数字加1；
 *                                   若（舍入位小于5）或者（舍入位等于5且前一位为偶数），则直接舍弃。即为银行家舍入模式。
 *                  ROUND_UNNECESSARY  断言请求的操作具有精确的结果，因此不需要舍入。
 *                                      如果对获得精确结果的操作指定此舍入模式，则抛出ArithmeticException。
 *
 */
public class NumberUtil {

    /**
     * 判断数据是否为小数或者整数
     * @param number
     * @return
     */
    public static boolean isNumber(String number) {
        if(number == null) {
            return false;
        }
        return number.trim().matches("^([\\-\\+])?\\d+(\\.\\d+)?$");
    }
    /**
     * 判断数据是否整数
     * @param number
     * @return
     */
    public static boolean isInteger(String number) {
        if(number == null) {
            return false;
        }
        return number.trim().matches("^([\\-\\+])?\\d+$");
    }


    /**
     * 判断是否全数字
     * @param number
     * @return
     */
    public static boolean isDigits(String number) {
        if(number == null) {
            return false;
        }
        return number.trim().matches("^\\d+$");
    }

    public static int max(int ...param) {
        if(param == null || param.length == 0) {
            throw new RuntimeException("判断数字长度不能为空");
        }

        int max = param[0];
        for(int i=1; i<param.length; ++i) {
            if(max < param[i]) {
                max = param[i];
            }
        }
        return max;
    }

    public static double max(double ...param) {
        if(param == null || param.length == 0) {
            throw new RuntimeException("判断数字长度不能为空");
        }
        double max = param[0];
        for(int i=1; i<param.length; ++i) {
            if(max < param[i]) {
                max = param[i];
            }
        }
        return max;
    }

    /**
     * 执行精准的乘法运算
     * @param v1
     * @return
     */
    public static double multiply(double ...v1) {
        if(v1 == null || v1.length == 0) {
            throw new RuntimeException("判断数字长度不能为空");
        }
        BigDecimal big = BigDecimal.valueOf(v1[0]);
        for (int i=1; i<v1.length; ++i) {
            big = big.multiply(BigDecimal.valueOf(v1[i]));
        }
        return big.doubleValue();
    }

    /**
     * 除法运算
     * @param v1:被除数
     * @param v2：除数
     * @param mode：进位方式
     * @param accuracy：保留小数位数
     * @return
     */
    public static double div(double v1, double v2, RoundingMode mode, int accuracy) {
        return BigDecimal.valueOf(v1).divide(BigDecimal.valueOf(v2),accuracy, mode).doubleValue();
    }



    public static double add(double ...v1) {
        if(v1 == null || v1.length == 0) {
            throw new RuntimeException("判断数字长度不能为空");
        }

        BigDecimal big = BigDecimal.valueOf(v1[0]);

        for(int i=1; i<v1.length; ++i) {
            big = big.add(BigDecimal.valueOf(v1[i]));
        }

        return big.doubleValue();
    }

    /**
     * 执行减法运算
     * @param v1：被减数
     * @param v2:减数
     * @return
     */
    public static double subtract (double v1, double v2) {
        return BigDecimal.valueOf(v1).subtract(BigDecimal.valueOf(v2)).doubleValue();
    }

    /**
     * 将double转string
     * @param v1
     * @param length：获取小数位数
     * @param mode:截取方式
     *            RoundingMode.UP 0舍1入
     *            RoundingMode.DOWN：直接舍弃掉舍入位
     *            ROUND_CEILING:正数则按照ROUND_UP方式，负数按照ROUND_DOWN方式，既向上取整
     *            RoundingMode.FLOOR:正数则按照ROUND_DOWN方式，负数按照ROUND_UP方式，既向下取整
     *            RoundingMode.HALF_UP：4舍5入
     *            RoundingMode.HALF_DOWN:5舍6入
     *            RoundingMode.HALF_EVEN:若（舍入位大于5）或者（舍入位等于5且前一位为奇数），则对舍入部分的前一位数字加1；
     *  *                                   若（舍入位小于5）或者（舍入位等于5且前一位为偶数），则直接舍弃。即为银行家舍入模式。
     *            RoundingMode.UNNECESSARY  断言请求的操作具有精确的结果，因此不需要舍入。
     *  *                                      如果对获得精确结果的操作指定此舍入模式，则抛出ArithmeticException。
     * @return
     */
    public static String toString(double v1, int length, RoundingMode mode) {
        return BigDecimal.valueOf(v1).setScale(length, mode).toString();
    }

}
